#include "rtc.h"
#include "delay.h"
#include "w55mh32_rtc.h"
#include "stdint.h"
#include "w55mh32_rcc.h"
#include "w55mh32_pwr.h"
#include "w55mh32_bkp.h"


// RTC中断标志
static volatile uint8_t rtc_30s_flag = 0;

/**
 * @brief 初始化RTC时钟
 *
 * 该函数用于初始化RTC时钟，包括配置外部低速晶振(LSE)、使能RTC时钟、设置RTC预分频值、设置初始时间等。
 *
 * @return uint8_t 如果初始化成功返回0，如果初始化失败返回1。
 */
uint8_t RTC_Init(void)
{
    uint8_t temp = 0;

    /* 使能 PWR 和 Backup 时钟 */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

    /* 允许访问 Backup 区域 */
    PWR_BackupAccessCmd(ENABLE);

    /* 复位 Backup 区域 */
    BKP_DeInit();

    /* 使能 LSI */
    RCC_LSICmd(ENABLE);

    /* 等待 LSI 准备好 */
    while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET && temp < 250)
    {
        temp++;
        delay_ms(10);
    }
    if (temp >= 250)
        return 1; // 初始化时钟失败,晶振有问题

    /* 选择 LSI 作为 RTC 时钟源 */
    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);

    /* 使能 RTC 时钟 */
    RCC_RTCCLKCmd(ENABLE);

    /* 等待 RTC 寄存器 同步
     * 因为 RTC 时钟是低速的，内环时钟是高速的，所以要同步
     */
    RTC_WaitForSynchro();

    /* 确保上一次 RTC 的操作完成 */
    RTC_WaitForLastTask();

    //	/* 使能 RTC 秒中断 */
    RTC_ITConfig(RTC_IT_SEC, ENABLE);

    /* 确保上一次 RTC 的操作完成 */
    RTC_WaitForLastTask();

    /* 设置 RTC 分频: 使 RTC 周期为 0.001s ,LSI 约为 40KHz */
    RTC_SetPrescaler(40000 - 1);

    /* 确保上一次 RTC 的操作完成 */
    RTC_WaitForLastTask();

    // 配置NVIC
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    return 0; // ok
}

/**
 * @brief  RTC秒中断处理函数
 */
void RTC_IRQHandler(void)
{
    static uint32_t rtc_second_count = 0;

    // 检查是否是RTC秒中断
    if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
    {
        // 增加秒计数
        rtc_second_count++;

        // 检查是否达到30秒
        if (rtc_second_count >= 30)
        {
            // 设置30秒标志
            rtc_30s_flag = 1;

            // 重置计数器
            rtc_second_count = 0;
        }

        // 清除RTC秒中断标志
        RTC_ClearITPendingBit(RTC_IT_SEC);

        // 等待写操作完成
        RTC_WaitForLastTask();
    }
}

/**
 * @brief  启动30秒RTC定时器
 */
void RTC_30Sec_Start(void)
{
    // 使能RTC时钟
    RCC_RTCCLKCmd(ENABLE);
    // 等待RTC寄存器同步
    RTC_WaitForSynchro();

    rtc_30s_flag = 0;
    RTC_SetCounter(0);
    RTC_WaitForLastTask();
}

/**
 * @brief  停止30秒RTC定时器
 */
void RTC_30Sec_Stop(void)
{
    // 禁用RTC时钟
    RCC_RTCCLKCmd(DISABLE);

    rtc_30s_flag = 0;
}

/**
 * @brief  检查RTC 30秒定时器是否超时
 * @retval 1:超时 0:未超时
 */
uint8_t RTC_30Sec_IsTimeout(void)
{
    if (rtc_30s_flag)
    {
        rtc_30s_flag = 0; // 清除标志
        return 1;
    }
    return 0;
}

/**
 * @brief  设置RTC时间
 * @param  hour: 小时 (0-23)
 * @param  minute: 分钟 (0-59)
 * @param  second: 秒 (0-59)
 */
void RTC_SetTime(uint8_t hour, uint8_t minute, uint8_t second)
{
    uint32_t time_in_seconds = hour * 3600 + minute * 60 + second;

    // 设置RTC计数器值
    RTC_SetCounter(time_in_seconds);

    // 等待写操作完成
    RTC_WaitForLastTask();
}

